package com.cry.todo.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.apache.commons.logging.Log;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;

import com.cry.app.core.log.Logger;
import com.cry.todo.domain.User;
import com.cry.todo.domain.audit.AuditRevision;
import com.cry.todo.domain.project.Category;
import com.cry.todo.domain.project.Project;
import com.cry.todo.domain.project.Status;
import com.cry.todo.service.ProjectService;
import com.cry.todo.service.UserService;
import com.cry.webapp.action.ActionSupport;
import com.cry.webapp.ui.MenuItem;
import com.cry.webapp.ui.datagrid.DataGrid;
import com.cry.webapp.ui.datagrid.DataGridColumn;
import com.cry.webapp.ui.datagrid.JQGridImpl;
import com.opensymphony.xwork2.Action;

public class ProjectAction extends ActionSupport { 
	@Logger 
	public Log log;
    
//	private final ArrayList<DataGridColumn> dataTableColumns = new ArrayList<DataGridColumn>() {
//		{
//			add(new DataGridColumn("id", getText("project.item.id"), false, false, true));
//			add(new DataGridColumn("number", getText("project.item.number"), false, false, false));
//			add(new DataGridColumn("name", getText("project.item.name"), false, false));
//			add(new DataGridColumn("createdBy.userName", getText("project.item.userName"), false, false));
//			add(new DataGridColumn("createdAt", getText("project.item.createdAt"), false, false));
//		}
//	};
	
	/**
	 * IoC injected services
	 */
	@Autowired
	private ProjectService projectService;
	@Autowired
	private UserService userService;

	@Valid
	private Project item;

	private int projectNumber;
	private String submitAction;
	private ArrayList<Project> parents;
	private ArrayList<User> usersList;
	private ArrayList<Category> categoriesList;
	private ArrayList<Status> statusesList;
	private List<AuditRevision<Project>> revisions;
	private String comment;
	private boolean prepared = false;
	private JQGridImpl dataGrid = new JQGridImpl();

	@Override
	public void prepare() {
		log.debug("projectNumber: " + getProjectNumber());
		if(projectNumber == 0) {
			item = new Project();
		} else {
			item = projectService.loadById(getProjectNumber());
		}
		prepared = true;		
	}
	
	
	public String showProject() {
		if(projectNumber == 0) projectNumber = 1;
		log.debug("projectNumber: " + getProjectNumber());
		item = projectService.loadById(getProjectNumber());
		
		this.parents = new ArrayList(projectService.getParents(item));
		
		return "success";
	}

	/**
	 * ajaxListDetails action method
	 * @return
	 */
	public String ajaxShowProjects() {
		log.debug("projectNumber: " + getProjectNumber());
		return "success";
	}

	/**
	 * ajaxShowAdd action method
	 */
	public String ajaxShowAddComment() {
		log.debug("projectNumber: " + getProjectNumber());
		
		return "success";
	}
	/**
	 * ajaxShowAdd action method
	 */
	public String ajaxAddComment() {
		log.debug("projectNumber: " + getProjectNumber());
		
		projectService.addComment(item, this.comment);
		
		return Action.NONE;
	}

	/**
	 * ajaxShowAdd action method
	 */
	public String ajaxShowAdd() {
		log.debug("projectNumber: " + getProjectNumber());

		Project parentProject = projectService.loadById(getProjectNumber());
		item = new Project();
		item.setId(0);
		item.setParentProject(parentProject);
		return "success";
	}

	/**
	 * ajaxShowEdit action method
	 */
	public String ajaxShowEdit() {
		log.debug("projectNumber: " + getProjectNumber());

		return "success";
	}

	/**
	 * ajaxSaveEdit action method
	 * @return
	 * @throws Exception 
	 */
	public String ajaxSave() throws Exception {
		log.debug("projectNumber: " + projectNumber );

		ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<ProjectAction>> constraits = validator.validate(this);
		
        for(ConstraintViolation<ProjectAction> constrait : constraits) {
        	if(super.getFieldErrors().get(constrait.getPropertyPath()) == null) {
        		super.addFieldError(constrait.getPropertyPath().toString(), constrait.getMessage());
        	}
        }
        /*
         * This is a new item
         */
        if(super.getFieldErrors().size() == 0) {
        	projectService.saveOrUpdate(item);
        } else {
        	HashMap<String, Object> result = new HashMap<String, Object>();
        	result.put("fieldErrors", super.getFieldErrors());
        	
        	response.setContentType("application/json");
            response.setStatus(HttpServletResponse.SC_OK);
            ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
            mapper.writeValue(response.getWriter(), result);
        }
		return Action.NONE;
	}

	/**
	 * @return
	 */
	public String ajaxShowDetails() {
		log.debug("projectNumber: " + getProjectNumber());
		return "success";
	}

	public String ajaxShowHistory() {
		revisions = projectService.findRevisionsbyId(getProjectNumber());

		for(AuditRevision<Project> revision: revisions) {
			System.out.println(revision.getRevisionEntity().getId());
			System.out.println(revision.getEntity().getUsers());
		}
		
		return "success";
	}
	
	/**
	 * Return with the project's subprojects in JSON to jquery datatables component
	 * @return
	 * @throws Exception
	 */
	public String jsonRefreshState() throws Exception {
		log.debug("projectNumber: " + getProjectNumber());

		HashMap<String, Object> result = new HashMap<String, Object>();

		result.put("projectNumber", projectNumber);
		
		if(projectNumber != 0 && item == null) {
			result.put("missing", true);
			
	        /*
	         * Tabs
	         */
	        ArrayList<Integer> tabs=new ArrayList<Integer>();
        	tabs.add(1);
        	tabs.add(2);
        	result.put("activeTab", 0);
        	result.put("disabledTabs", tabs);
	        
	        /*
	         * Menu
	         */
	        /*ArrayList<MenuItem> menu=new ArrayList<MenuItem>();
	    	result.put("menuItems", menu);*/
		} else {
	        result.put("projectName", item.getName());
		
	        /*
	         * Fill the projects parentId
	         */
	        
	        ArrayList<MenuItem> navBar=new ArrayList<MenuItem>();
	        for(Project project : projectService.getParents(this.item)) {
	        	if(project.getId() != getProjectNumber()) {
	            	navBar.add(new MenuItem(project.getName(), "project/showProject#projectNumber=" + project.getId()));
	        	} else {
	            	navBar.add(new MenuItem(project.getName(), ""));
	        	}
	        }
	        result.put("navBar", navBar);
	
	        /*
	         * Tabs
	         */
	        ArrayList<Integer> tabs=new ArrayList<Integer>();
	        if(getProjectNumber() == 1) {
	        	tabs.add(0);
	        	tabs.add(2);
	        	result.put("activeTab", 1);
	        	result.put("disabledTabs", tabs);
	        } 
	
	        /*
	         * Menu
	         */
	        ArrayList<MenuItem> menu=new ArrayList<MenuItem>();
	        if(getProjectNumber() == 1) {
	        	menu.add(new MenuItem("add", getText("item.add"), "project/ajaxShowAdd?projectNumber=" + projectNumber, "modal"));
	        } else {
	        	menu.add(new MenuItem("add", getText("item.add"), "project/ajaxShowAdd?projectNumber=" + projectNumber, "modal"));
	        	menu.add(new MenuItem("edit", getText("item.edit"), "project/ajaxShowEdit?projectNumber=" + projectNumber, "modal"));
	        	menu.add(new MenuItem("comment", getText("item.newComment"), "project/ajaxShowAddComment?projectNumber=" + projectNumber, "modal"));
	        }
	    	result.put("menuItems", menu);
		}
		
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_OK);
        ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
        mapper.writeValue(response.getWriter(), result);

		return Action.NONE;
		
	}

	/**
	 * Return with the project's subprojects in JSON to jquery datatables component
	 * @return
	 * @throws Exception
	 */
	public String jsonShowProjects() throws Exception {
		log.debug("projectNumber: " + getProjectNumber());

        DataGrid dataTable = new JQGridImpl();
        dataTable.init(request);

        dataTable.setTotalRecord(projectService.countChildren(getProjectNumber()));
		
		Set<Project> children = new LinkedHashSet<Project>(projectService.findChildren(getProjectNumber(), dataTable.getStartRow(), dataTable.getDisplayRow(), dataTable.getOrderColumn(), dataTable.getOrderDir()));
		
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_OK);

		//dataTable.setColumns(dataTableColumns);
		dataTable.setList(children);
		HashMap<String, Object> userData = new HashMap<String, Object>(); 
		userData.put("parent", item.getParentProject());

		dataTable.setUserData(userData);

		response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_OK);
        ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
        mapper.writeValue(response.getWriter(), dataTable.buildJSONResponse());
		
		return Action.NONE;
	}

//	public ArrayList<DataGridColumn> getDataTableColumns() {
//		return dataTableColumns;
//	}

	public int getProjectNumber() {
		return projectNumber;
	}

	public void setProjectNumber(int projectNumber) {
		this.projectNumber = projectNumber;
	}

	public String getSubmitAction() {
		return submitAction;
	}

	public void setSubmitAction(String submitAction) {
		this.submitAction = submitAction;
	}

	public ArrayList<Project> getParents() {
		return parents;
	}

	public void setParents(ArrayList<Project> parents) {
		this.parents = parents;
	}

	/**
	 * Retrieve list of users
	 * @return
	 */
	public ArrayList<User> getUsersList() {
		System.out.println("getUsersList");
		if( usersList == null) {
			usersList = userService.loadAll();
		}
		return usersList;
	}

	/**
	 * Retrieve project categories list
	 * @return
	 */
	public ArrayList<Category> getCategoriesList() {
		if(categoriesList == null) {
			categoriesList = new ArrayList(projectService.loadCategories());
		}
		return categoriesList;
	}

	/**
	 * Retrieve project statuses list
	 * @return
	 */
	public ArrayList<Status> getStatusesList() {
		if(statusesList == null) {
			statusesList = new ArrayList(projectService.loadStatuses());
		}
		return statusesList;
	}


	/**
	 * 
	 * @param ids
	 * @throws Exception
	 */
	public void setStatusId(Integer id) throws Exception {
		if (!prepared) return;
		Status status = new Status();
		status.setId(id);
		item.setStatus(status);
	}
	
	/**
	 * 
	 * @param id
	 * @throws Exception
	 */
	public void setSupervisorId(Integer id) throws Exception {
		if (!prepared) return;
		User supervisor = new User();
		supervisor.setId(id);
		item.setSupervisor(supervisor);
	}

	/**
	 * 
	 * @param ids
	 * @throws Exception
	 */
	public void setUsersId(ArrayList<Integer> ids) throws Exception {
		if (!prepared) return;
		
		item.setUsers(ids);
	}

	/**
	 * Set selected categories
	 * @param ids
	 * @throws Exception 
	 */
	public void setCategoriesId(ArrayList<Integer> ids) throws Exception {
		if (!prepared) return;
		item.setCategories(ids);
	}

	public Project getItem() {
		return item;
	}

	public void setItem(Project item) {
		this.item = item;
	}

	public List<AuditRevision<Project>> getRevisions() {
		return revisions;
	}

	public String getComment() {
		return comment;
	}

	public void setComment(String comment) {
		this.comment = comment;
	}


	public JQGridImpl getDataGrid() {
		return dataGrid;
	}


	public void setDataGrid(JQGridImpl dataGrid) {
		this.dataGrid = dataGrid;
	}


}
